﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace EnvironmentManagerSystem.A
{
    /// <summary>
    /// 画出柱形图片类
    /// </summary>
    public class ChartImage
    {
        private ImageAttribute imageAtt = new ImageAttribute();
        private List<Chart> chartItem = new List<Chart>();
        private List<BrokenLine> brokenLineItem = new List<BrokenLine>();
        /// <summary>
        /// 图片中所有柱形最高一个底部文本的高度
        /// </summary>
        int bottomTextHeight = 0;

        /// <summary>
        /// 设置图片的属性
        /// </summary>
        public ImageAttribute ImageAtt
        {
            get
            {
                return imageAtt;
            }
        }
        /// <summary>
        /// 图片中的柱形集合
        /// </summary>
        public List<Chart> ChartItems
        {
            get
            {
                return chartItem;
            }
        }
        /// <summary>
        /// 获取或设置图片中柱形的个数.
        /// </summary>
        public int ChartCount
        {
            get
            {
                return chartItem.Count;
            }
            set
            {
                for (int i = 0; i < value; i++)
                {
                    chartItem.Add(new Chart());
                }
            }
        }
        /// <summary>
        /// 图片中的虚线集合
        /// </summary>
        public List<BrokenLine> BrokenLineItems
        {
            get
            {
                return brokenLineItem;
            }
        }
        /// <summary>
        /// 获得图片
        /// </summary>
        /// <returns></returns>
        public Bitmap GetImage()
        {
            try
            {
                Bitmap bmp = new Bitmap(this.ImageAtt.Width, this.ImageAtt.Height);
                Graphics g = Graphics.FromImage(bmp);
                //绘制底色
                g.FillRectangle(new SolidBrush(this.ImageAtt.BackColor), new Rectangle(0, 0, this.ImageAtt.Width, this.ImageAtt.Height));
                //求出柱形底部文本最高一个的高度
                foreach (Chart c in this.ChartItems)
                {
                    if ((int)(c.BottomTextFont.GetHeight()) > bottomTextHeight)
                    {
                        bottomTextHeight = (int)c.BottomTextFont.GetHeight();
                    }
                }

                this.DrawBorderAndCaption(g);
                this.DrawChart(g);
                this.DrawBrokenLine(g);
                return bmp;

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 绘制图片中的虚线
        /// </summary>
        /// <param name="g"></param>
        private void DrawBrokenLine(Graphics g)
        {
            foreach (BrokenLine b in this.BrokenLineItems)
            {
                Pen p = new Pen(b.BrokenLineColor);
                p.DashStyle = b.DashStyle;
                if (this.ImageAtt.CPlace == CaptionPlace.Left)
                {
                    //绘制虚线
                    g.DrawLine(p, this.ImageAtt.CaptionFont.GetHeight() + 2, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY, this.ImageAtt.Width, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY);
                    //绘制虚线上的文本
                    if (this.ImageAtt.CaptionFont.GetHeight() + 2 + b.TextX + g.MeasureString(b.Text, b.TextFont).Width > this.ImageAtt.Width)
                    {
                        b.TextX = this.ImageAtt.Width - (int)g.MeasureString(b.Text, b.TextFont).Width;
                    }
                    if (b.TextPlace == TextPlace.Up)
                    {
                        g.DrawString(b.Text, b.TextFont, new SolidBrush(b.TextColor), this.ImageAtt.CaptionFont.GetHeight() + 2 + b.TextX, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY - b.TextFont.GetHeight());
                    }
                    else if (b.TextPlace == TextPlace.Bosom)
                    {
                        g.DrawString(b.Text, b.TextFont, new SolidBrush(b.TextColor), this.ImageAtt.CaptionFont.GetHeight() + 2 + b.TextX, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY - (b.TextFont.GetHeight() / 2));
                    }
                    else
                    {
                        g.DrawString(b.Text, b.TextFont, new SolidBrush(b.TextColor), this.ImageAtt.CaptionFont.GetHeight() + 2 + b.TextX, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY + 2);
                    }
                }
                else
                {
                    if (this.ImageAtt.CPlace == CaptionPlace.Top)
                    {
                        //绘制虚线
                        g.DrawLine(p, 0, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY, this.ImageAtt.Width, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY);
                        if (b.TextX + g.MeasureString(b.Text, b.TextFont).Width > this.ImageAtt.Width)
                        {
                            b.TextX = this.ImageAtt.Width - (int)g.MeasureString(b.Text, b.TextFont).Width;
                        }
                    }
                    else
                    {
                        //绘制虚线
                        g.DrawLine(p, 0, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY, this.ImageAtt.Width - this.ImageAtt.CaptionFont.GetHeight() - 2, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY);
                        if (b.TextX + g.MeasureString(b.Text, b.TextFont).Width + this.ImageAtt.CaptionFont.GetHeight() + 2 > this.ImageAtt.Width)
                        {
                            b.TextX = (int)(this.ImageAtt.Width - g.MeasureString(b.Text, b.TextFont).Width - this.ImageAtt.CaptionFont.GetHeight() - 2);
                        }
                    }
                    //绘制虚线上的文本
                    if (b.TextPlace == TextPlace.Up)
                    {
                        g.DrawString(b.Text, b.TextFont, new SolidBrush(b.TextColor), b.TextX, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY - b.TextFont.GetHeight());
                    }
                    else if (b.TextPlace == TextPlace.Bosom)
                    {
                        g.DrawString(b.Text, b.TextFont, new SolidBrush(b.TextColor), b.TextX, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY - (b.TextFont.GetHeight() / 2));
                    }
                    else
                    {
                        g.DrawString(b.Text, b.TextFont, new SolidBrush(b.TextColor), b.TextX, this.ImageAtt.Height - bottomTextHeight - b.BrokenLineY + 2);
                    }
                }
            }
        }

        /// <summary>
        /// 绘制图片中的柱形
        /// </summary>
        /// <param name="g"></param>
        private void DrawChart(Graphics g)
        {
            //排列柱形所需要的最小间隔总和
            int minWidth = 10 * (this.ChartCount + 1);

            //柱形宽度的总和
            int chartWidthCount = 0;
            for (int i = 0; i < this.ChartCount; i++)
            {
                chartWidthCount += this.ChartItems[i].Width;
            }
            if (this.ImageAtt.CPlace == CaptionPlace.Top)
            {
                if (minWidth + chartWidthCount > this.ImageAtt.Width)
                {
                    throw new Exception("要绘制的柱形宽度总和无法在该尺寸的图片中绘制,柱形宽度总和超过图片宽度,绘制失败!");
                }
            }
            else
            {
                if (minWidth + chartWidthCount + this.ImageAtt.CaptionFont.GetHeight() + 2 > this.ImageAtt.Width)
                {
                    throw new Exception("要绘制的柱形宽度总和无法在该尺寸的图片中绘制,柱形宽度总和超过图片宽度,绘制失败!");
                }
            }

            //每个柱形之间的实际间隔
            int alternation = 0;
            //当前正在绘制柱形的X坐标
            int drawX = 0;
            if (this.ImageAtt.CPlace == CaptionPlace.Top)
            {
                alternation = (this.ImageAtt.Width - chartWidthCount) / (this.ChartCount + 1);
                drawX = alternation;
            }
            else if (this.ImageAtt.CPlace == CaptionPlace.Right)
            {
                alternation = (int)(this.ImageAtt.Width - chartWidthCount - this.ImageAtt.CaptionFont.GetHeight() + 2) / (this.ChartCount + 1);
                drawX = alternation;
            }
            else
            {
                alternation = (int)(this.ImageAtt.Width - chartWidthCount - this.ImageAtt.CaptionFont.GetHeight() + 2) / (this.ChartCount + 1);
                drawX = (int)(alternation + this.ImageAtt.CaptionFont.GetHeight() + 2);
            }

            int j = 1;
            foreach (Chart c in ChartItems)
            {
                if (this.ImageAtt.CPlace == CaptionPlace.Top)
                {
                    if (c.Height + c.CaptionFont.GetHeight() + this.ImageAtt.CaptionFont.GetHeight() + 2 > this.ImageAtt.Height)
                    {
                        throw new Exception("绘制的第" + j + "个柱形加标题文字的高度超过了图片的高度,无法绘制!");
                    }
                }
                else
                {
                    if (c.Height + c.CaptionFont.GetHeight() > this.ImageAtt.Height)
                    {
                        throw new Exception("绘制的第" + j + "个柱形加标题文字的高度超过了图片的高度,无法绘制!");
                    }
                }
                //以颜色填充柱形                   
                if (c.ColorType)
                {
                    g.FillRectangle(new SolidBrush(c.ChartColor), new Rectangle(drawX, this.ImageAtt.Height - c.Height - bottomTextHeight, c.Width, c.Height - 2));
                }
                else
                {
                    LinearGradientBrush lgb = new LinearGradientBrush(new Rectangle(drawX, this.ImageAtt.Height - c.Height, c.Width, c.Height - 2), c.ChartColor, c.ChartColor2, 0.0f);
                    g.FillRectangle(lgb, new Rectangle(drawX, this.ImageAtt.Height - c.Height - bottomTextHeight, c.Width, c.Height - 2));
                }
                //绘制柱形的边框
                g.DrawRectangle(new Pen(c.BorderColor), new Rectangle(drawX, this.ImageAtt.Height - c.Height - bottomTextHeight - 1, c.Width, c.Height));
                //绘制柱形的标题文字
                SizeF TSize = g.MeasureString(c.Caption, c.CaptionFont);
                int captionX = (int)(c.Width - TSize.Width) / 2;
                g.DrawString(c.Caption, c.CaptionFont, new SolidBrush(c.CaptionColor), drawX + captionX, (int)(this.ImageAtt.Height - bottomTextHeight - c.Height - c.CaptionFont.GetHeight()));
                //绘制柱形的底部文本
                SizeF BSize = g.MeasureString(c.BottomText, c.BottomTextFont);
                int BTextX = (int)(c.Width - BSize.Width) / 2;
                g.DrawString(c.BottomText, c.BottomTextFont, new SolidBrush(c.BottomTextColor), drawX + BTextX, this.imageAtt.Height - bottomTextHeight + 1);
                //移动绘制柱形的X坐标
                drawX += c.Width + alternation;
                j++;
            }

        }

        /// <summary>
        /// 绘制图片的边框,刻度和标题
        /// </summary>
        private void DrawBorderAndCaption(Graphics g)
        {
            //求出标题文字的宽度
            SizeF ytxtSize = g.MeasureString(this.ImageAtt.Caption, this.ImageAtt.CaptionFont);
            if (this.ImageAtt.CPlace == CaptionPlace.Left)
            {
                //左侧文字
                float x = (this.ImageAtt.Height - ytxtSize.Width) / 2;
                g.TranslateTransform(0, this.ImageAtt.Height);
                g.RotateTransform(-90);
                g.DrawString(this.ImageAtt.Caption, this.ImageAtt.CaptionFont, new SolidBrush(this.ImageAtt.CaptionColor), x, 0);
                g.RotateTransform(90);
                g.TranslateTransform(0, -this.ImageAtt.Height);
                g.DrawRectangle(new Pen(Color.Black, 2.0f), new Rectangle((int)(this.ImageAtt.CaptionFont.GetHeight() + 2), 0, (int)(this.ImageAtt.Width - (this.ImageAtt.CaptionFont.GetHeight() + 2)), this.ImageAtt.Height - bottomTextHeight));
            }
            else if (this.ImageAtt.CPlace == CaptionPlace.Right)
            {
                float x = (this.ImageAtt.Height - ytxtSize.Width) / 2;
                g.TranslateTransform(this.ImageAtt.Width, 0);
                g.RotateTransform(90);
                g.DrawString(this.ImageAtt.Caption, this.ImageAtt.CaptionFont, new SolidBrush(this.ImageAtt.CaptionColor), x, 0);
                g.RotateTransform(-90);
                g.TranslateTransform(-this.ImageAtt.Width, 0);
                g.DrawRectangle(new Pen(Color.Black, 2.0f), new Rectangle(0, 0, (int)(this.ImageAtt.Width - (this.ImageAtt.CaptionFont.GetHeight() + 2)), this.ImageAtt.Height - bottomTextHeight));
            }
            else
            {
                float x = (this.ImageAtt.Width - ytxtSize.Width) / 2;
                g.DrawString(this.ImageAtt.Caption, this.ImageAtt.CaptionFont, new SolidBrush(this.ImageAtt.CaptionColor), x, 0);
                g.DrawRectangle(new Pen(Color.Black, 2.0f), new Rectangle(0, (int)(this.ImageAtt.CaptionFont.GetHeight() + 2), this.ImageAtt.Width, (int)(this.ImageAtt.Height - (this.ImageAtt.CaptionFont.GetHeight() + 2 + bottomTextHeight))));
            }

            //绘制竖着的边格
            for (int i = 1; this.ImageAtt.Height - (this.ImageAtt.BorderDistance * i) > 0; i++)
            {
                if (this.ImageAtt.CPlace == CaptionPlace.Left)
                {
                    if (i % 5 == 0)
                    {
                        g.DrawLine(new Pen(Color.Red), this.ImageAtt.CaptionFont.GetHeight() + 2, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i), this.ImageAtt.CaptionFont.GetHeight() + 10, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i));
                        g.DrawString("" + (this.ImageAtt.LeftGraduationValue * (i / 5)), new Font("宋体", 8), new SolidBrush(Color.Red), this.ImageAtt.CaptionFont.GetHeight() + 10, this.ImageAtt.Height - bottomTextHeight - (this.imageAtt.BorderDistance * i) - (new Font("宋体", 8).GetHeight() / 2));

                    }
                    else
                    {
                        g.DrawLine(new Pen(Color.Black), this.ImageAtt.CaptionFont.GetHeight() + 2, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i), this.ImageAtt.CaptionFont.GetHeight() + 8, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i));
                    }
                }
                else if (this.ImageAtt.CPlace == CaptionPlace.Top)
                {
                    if (this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i) - (this.ImageAtt.CaptionFont.GetHeight() + 2) < 0)
                    {
                        break;
                    }
                    if (i % 5 == 0)
                    {
                        g.DrawLine(new Pen(Color.Red), 0, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i), 8, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i));
                        g.DrawString("" + (this.ImageAtt.LeftGraduationValue * (i / 5)), new Font("宋体", 8), new SolidBrush(Color.Red), 8, this.ImageAtt.Height - bottomTextHeight - (this.imageAtt.BorderDistance * i) - (new Font("宋体", 8).GetHeight() / 2));
                    }
                    else
                    {
                        g.DrawLine(new Pen(Color.Black), 0, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i), 6, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i));
                    }

                }
                else
                {
                    if (i % 5 == 0)
                    {
                        g.DrawLine(new Pen(Color.Red), 0, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i), 8, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i));
                        g.DrawString("" + (this.ImageAtt.LeftGraduationValue * (i / 5)), new Font("宋体", 8), new SolidBrush(Color.Red), 8, this.ImageAtt.Height - bottomTextHeight - (this.imageAtt.BorderDistance * i) - (new Font("宋体", 8).GetHeight() / 2));
                    }
                    else
                    {
                        g.DrawLine(new Pen(Color.Black), 0, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i), 6, this.ImageAtt.Height - bottomTextHeight - (this.ImageAtt.BorderDistance * i));
                    }
                }
            }

            //绘制横着的边格
            for (int i = 1; this.ImageAtt.BorderDistance * i < this.ImageAtt.Width; i++)
            {
                if (this.ImageAtt.CPlace == CaptionPlace.Left)
                {
                    if (this.ImageAtt.CaptionFont.GetHeight() + 2 + this.ImageAtt.BorderDistance * i > this.ImageAtt.Width)
                    {
                        break;
                    }
                    if (i % 5 == 0)
                    {
                        g.DrawLine(new Pen(Color.Red), this.ImageAtt.CaptionFont.GetHeight() + 2 + this.ImageAtt.BorderDistance * i, 0, this.ImageAtt.CaptionFont.GetHeight() + 2 + this.ImageAtt.BorderDistance * i, 10);
                    }
                    else
                    {
                        g.DrawLine(new Pen(Color.Black), this.ImageAtt.CaptionFont.GetHeight() + 2 + this.ImageAtt.BorderDistance * i, 0, this.ImageAtt.CaptionFont.GetHeight() + 2 + this.ImageAtt.BorderDistance * i, 6);
                    }
                }
                else if (this.ImageAtt.CPlace == CaptionPlace.Top)
                {
                    if (i % 5 == 0)
                    {
                        g.DrawLine(new Pen(Color.Red), this.ImageAtt.BorderDistance * i, this.ImageAtt.CaptionFont.GetHeight() + 2, this.ImageAtt.BorderDistance * i, this.ImageAtt.CaptionFont.GetHeight() + 12);
                    }
                    else
                    {
                        g.DrawLine(new Pen(Color.Black), this.ImageAtt.BorderDistance * i, this.ImageAtt.CaptionFont.GetHeight() + 2, this.ImageAtt.BorderDistance * i, this.ImageAtt.CaptionFont.GetHeight() + 8);
                    }
                }
                else
                {
                    if (this.ImageAtt.CaptionFont.GetHeight() + 2 + this.ImageAtt.BorderDistance * i > this.ImageAtt.Width)
                    {
                        break;
                    }
                    if (i % 5 == 0)
                    {
                        g.DrawLine(new Pen(Color.Red), this.ImageAtt.BorderDistance * i, 0, this.ImageAtt.BorderDistance * i, 10);
                    }
                    else
                    {
                        g.DrawLine(new Pen(Color.Black), this.ImageAtt.BorderDistance * i, 0, this.ImageAtt.BorderDistance * i, 6);
                    }
                }
            }
        }
    }
}
